package timbap.visualizer.coreplugins;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import processing.core.PApplet;
import timbap.visualizer.api.model.PlaylistEntry;
import timbap.visualizer.api.model.RecordItem;
import timbap.visualizer.api.model.TimeCode;
import timbap.visualizer.api.plugin.container.AbstractKeepAliveModeController;
import timbap.visualizer.api.plugin.container.PluginSwitchCommand;

import java.io.File;

public class DefaultPlaybackModeControlImpl extends AbstractKeepAliveModeController {

    private static final Log LOG = LogFactory.getLog(DefaultPlaybackModeControlImpl.class);
    
    private static final String NO_FILE_URI_STRING = "file://";
    private static final String PLAY_COMMAND_ADDRESS_PATTERN = "/loadfile";
    private static final float RETURN_SEGMENT_FRACTIONAL_SIZE = 0.05f;
    private static final float MOVEMENT_DETECTION_THRESHOLD = 0.1f;

    private float rotation;

    @Override
    public void activate() {
        super.activate();
        PlaylistEntry tSelectedPlaylistEntry = getContext().getRecordItemManager().getSelectedRecordItem().getPlaylistEntry();
        if (!getContext().getRecordItemManager().getSelectedRecordItem().isPlaying()) {
            sendPlayCommand(tSelectedPlaylistEntry.getAudioFile());
        }
    }

    @Override
    public void passivate() {
        getContext().getMessagingManager().sendStringMessage(PLAY_COMMAND_ADDRESS_PATTERN, NO_FILE_URI_STRING);
        getContext().getRecordItemManager().getSelectedRecordItem().setPlaying(false);
        super.passivate();
    }

    @Override
    public void timeCodeUpdated(TimeCode pTimeCode) {
        super.timeCodeUpdated(pTimeCode);
        calcTurntableRotation();
        if (pTimeCode.getSignalPower() > MOVEMENT_DETECTION_THRESHOLD) {
            keepAlive();
        }       
        updateItems();
    }

    @Override
    public void keepAliveExpired() {
        float tRotation = getRotation();
        if (PApplet.abs(tRotation - 0.5f) < RETURN_SEGMENT_FRACTIONAL_SIZE) {
            publishPluginSwitchCommand(PluginSwitchCommand.PREVIOUS);
        } else {
            publishPluginSwitchCommand(PluginSwitchCommand.NEXT);
        }
    }

    public void sendPlayCommand(File pAudioFile) {

        String tFileAsUtf8URIString = NO_FILE_URI_STRING;
        if (pAudioFile != null) {
            tFileAsUtf8URIString = pAudioFile.getAbsoluteFile().toURI().toASCIIString();
        }
        getContext().getMessagingManager().sendStringMessage(
                PLAY_COMMAND_ADDRESS_PATTERN, tFileAsUtf8URIString);
        getContext().getRecordItemManager().getSelectedRecordItem().setPlaying(true);
    }


    private void calcTurntableRotation() {
        
        float tRotation = 0;
        if (getContext().getRecordItemManager().getRecordItemCount() > 0) {
            float tItemRotation = getTimeCode().getNormalizedAbsolutePosition() 
                                  * getContext().getPlaylistManager().getPlaylistSize() 
                                  / getContext().getRecordItemManager().getRecordItemCount();
            tRotation = (tItemRotation - (int)Math.floor(tItemRotation));
        }
        rotation = tRotation;
    }

    
    protected void updateItems() {
        
        RecordItem tSelectedRecordItem = getContext().getRecordItemManager().getSelectedRecordItem();
        
        tSelectedRecordItem.getTransformation().setXTranslation(0);
        tSelectedRecordItem.getTransformation().setYTranslation(0);
        tSelectedRecordItem.getTransformation().setScaleFactor(1);
        tSelectedRecordItem.getTransformation().setAlphaValue(1);

        tSelectedRecordItem.getTransformation().setRotation(PApplet.map(getRotation(),0,1,-PApplet.PI,PApplet.PI));
        tSelectedRecordItem.getTransformation().setXRotation(0);
        tSelectedRecordItem.setFractionPlayed(getTimeCode().getFractionPlayed());
        
    }

    public float getRotation() {
        return rotation;
    }

}
